/*
 * Copyright (c) 2022. China Mobile (SuZhou) Software Technology Co.,Ltd. All rights reserved.
 * Lakehouse is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

package com.chinamobile.cmss.lakehouse.core.config;

import java.util.HashMap;
import java.util.Map;

public class BasicConfiguration {

    private final HashMap<String, Object> confData;

    public BasicConfiguration() {
        this.confData = new HashMap<>();
    }

    public void addAll(Map<String, ?> other) {
        synchronized (this.confData) {
            confData.putAll(other);
        }
    }

    public <T> void set(String option, T value) {
        setValueInternal(option, value);
    }

    public <T> void set(ConfigOption<T> option, T value) {
        setValueInternal(option.key(), value);
    }

    <T> void setValueInternal(String key, T value) {
        if (key == null) {
            throw new NullPointerException("Key must not be null.");
        }
        if (value == null) {
            throw new NullPointerException("Value must not be null.");
        }

        synchronized (this.confData) {
            this.confData.put(key, value);
        }
    }

    public String getString(String key) {
        Object rawValue = getRawValue(key);
        return convertToString(rawValue, null);
    }

    public String getString(ConfigOption<String> configOption) {
        Object rawValue = getRawValue(configOption.key());
        return convertToString(rawValue, configOption.defaultValue());
    }

    public Integer getInteger(String key) {
        Object rawValue = getRawValue(key);
        return convertToInt(rawValue, null);
    }

    public Integer getInteger(ConfigOption<Integer> configOption) {
        Object rawValue = getRawValue(configOption.key());
        return convertToInt(rawValue, configOption.defaultValue());
    }

    public Integer getBoolean(String key) {
        Object rawValue = getRawValue(key);
        return convertToInt(rawValue, null);
    }

    public Boolean getBoolean(ConfigOption<Boolean> configOption) {
        Object rawValue = getRawValue(configOption.key());
        return convertToBoolean(rawValue, configOption.defaultValue());
    }

    private Object getRawValue(String key) {
        if (key == null) {
            throw new NullPointerException("Key must not be null.");
        }

        synchronized (this.confData) {
            return this.confData.get(key);
        }
    }

    private String convertToString(Object obj, String defaultValue) {
        return obj != null ? obj.toString() : defaultValue;
    }

    private Integer convertToInt(Object obj, Integer defaultValue) {
        if (obj == null) {
            return defaultValue;
        }

        try {
            return Integer.parseInt(obj.toString());
        } catch (NumberFormatException e) {
            return defaultValue;
        }
    }

    private Boolean convertToBoolean(Object obj, Boolean defaultValue) {
        if (obj == null) {
            return defaultValue;
        }

        if (obj.getClass() == Boolean.class) {
            return (Boolean) obj;
        }

        switch (obj.toString().trim().toUpperCase()) {
            case "TRUE":
                return true;
            case "FALSE":
                return false;
            default:
                return defaultValue;
        }
    }

}
